/* 
 * Copyright [2018] [Alex/libo(liboware@gmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.codex.redis.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

import com.hyts.codex.redis.model.JedisConnection;
import com.hyts.codex.redis.service.IDGenApi;

import lombok.AllArgsConstructor;
import redis.clients.jedis.Jedis;

/** 
 * @author LiBo/Alex
 * @see com.hyts.ssm.api.IDGenApi
 * @since V1.0
 * @version V1.0 
 */
@AllArgsConstructor
public class IDGenService implements IDGenApi{
    
    /**
     * 默认 0 
     */
    //@Setter
    private final int dbIndex;
        
    /**
     * redisConnection object
     */
    //@Setter
    private final JedisConnection connection;
    
    /**
     * @constructor：IDGenService
     */
    public IDGenService(JedisConnection connection) {
        this.connection = connection;
        dbIndex = 0;
    }
    
    /* 
     * (非 Javadoc)
     * @param key
     * @return
     * @see com.hyts.ssm.api.IDGenApi#genIdDaily(java.lang.String)  
     * @exception
     */ 
    @Override
    public Long genIdDaily(String key) {
        return genIdDaily(key,DEFAULT_ID_LENGTH,DEFAULT_JOIN_DAY_HEAD);
    }

    /* 
     * (非 Javadoc)
     * @param key
     * @param haveDay
     * @return
     * @see com.hyts.ssm.api.IDGenApi#genIdDaily(java.lang.String, java.lang.Boolean)  
     * @exception
     */ 
    @Override
    public Long genIdDaily(String key, Boolean haveDay) {
        return genIdDaily(key,DEFAULT_ID_LENGTH,haveDay);
    }

    /* (非 Javadoc)
     * @param key
     * @param length
     * @param haveDay
     * @return
     * @see com.hyts.ssm.api.IDGenApi#genIdDaily(java.lang.String, java.lang.Integer, java.lang.Boolean)  
     * @exception
     */ 
    
    @Override
    public Long genIdDaily(String key, Integer length, Boolean haveDay) {
       return commonTemplate(key,length,haveDay,true);
    }
    
    /* 
     * (非 Javadoc)
     * @param key
     * @return
     * @see com.hyts.ssm.api.IDGenApi#genId(java.lang.String)  
     * @exception
     */ 
    @Override
    public Long genId(String key) {
        return genId(key,DEFAULT_ID_LENGTH,DEFAULT_JOIN_DAY_HEAD);
    }

    /* (非 Javadoc)
     * @param key
     * @param length
     * @return
     * @see com.hyts.ssm.api.IDGenApi#genId(java.lang.String, java.lang.Integer)  
     * @exception
     */ 
    
    @Override
    public Long genId(String key, Integer length) {
        return genId(key,length,DEFAULT_JOIN_DAY_HEAD);
    }

    /* (非 Javadoc)
     * @param key
     * @param length
     * @param haveDay
     * @return
     * @see com.hyts.ssm.api.IDGenApi#genId(java.lang.String, java.lang.Integer, java.lang.Boolean)  
     * @exception
     */ 
    
    @Override
    public Long genId(String key, Integer length, Boolean haveDay) {
        return commonTemplate(key,length,haveDay,false);
    }
    
    
    /**
     * @param key
     * @param length
     * @param haveDay
     * @param isIntervalDaily
     * @return
     * @exception
     */
    private Long commonTemplate(String key, Integer length, Boolean haveDay,Boolean isIntervalDaily) {
        //获取为空则在获取一次
        Jedis session = connection.openSession().orElse(connection.openSession().get());
        session.select(dbIndex);
        String dateFormatStr = LocalDateTime.
                now(ZoneId.systemDefault()).
                format(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
        String realKey = "".concat(dateFormatStr).concat(DEFAULT_SPLIT_TOKEN).concat(key);
        Long index;
        try {
            index = session.incr(realKey);
            if (isIntervalDaily && index == 1) {
                Long startTime = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
                Long endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX).toInstant(ZoneOffset.of("+8"))
                        .toEpochMilli();
                session.expire(realKey, (int) (endTime - startTime));
            }
            if (haveDay) {
                return format(index, length, dateFormatStr);
            } 
        } finally {
            if (session != null) {
                session.close();
            }
        }
        return index;
    }
    

}
